package com.gxar.quick.ar.server.base.sdk;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gxar.common.entity.SystemCodeEnum;
import com.gxar.common.utils.AssertUtils;
import com.gxar.common.utils.CollectionUtils;
import com.gxar.common.utils.JacksonUtils;
import com.gxar.common.utils.StringUtils;
import com.gxar.quick.ar.server.base.common.constant.WechatPayConstant;
import com.gxar.quick.ar.server.base.common.enums.ComboConfigItemEnum;
import com.gxar.quick.ar.server.base.common.enums.WechatTradeStateEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderProductTypeEnum;
import com.gxar.quick.ar.server.base.common.enums.order.OrderStatusEnum;
import com.gxar.quick.ar.server.base.common.properties.WechatPayProperties;
import com.gxar.quick.ar.server.base.common.utils.AesUtils;
import com.gxar.quick.ar.server.base.model.combo.mapper.ComboMapStruct;
import com.gxar.quick.ar.server.base.model.combo.vo.ComboConfigInfoVO;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPayAmountInfo;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPayResourceInfo;
import com.gxar.quick.ar.server.base.model.pay.info.WechatPrepayAttachInfo;
import com.gxar.quick.ar.server.base.model.pay.vo.request.WechatNotifyRequest;
import com.gxar.quick.ar.server.base.model.pay.vo.request.WechatPrepayRequest;
import com.gxar.quick.ar.server.base.model.pay.vo.response.WechatPrepayResponse;
import com.gxar.quick.ar.server.base.model.pay.vo.response.WechatTransactionResponse;
import com.gxar.quick.ar.server.db.mapper.SlotMapper;
import com.gxar.quick.ar.server.db.mapper.UserConfigMapper;
import com.gxar.quick.ar.server.db.mapper.WorksMapper;
import com.gxar.quick.ar.server.db.model.ComboEntity;
import com.gxar.quick.ar.server.db.model.TransactionWechatEntity;
import com.gxar.quick.ar.server.db.model.UserConfigEntity;
import com.gxar.quick.ar.server.db.model.WorksEntity;
import com.gxar.quick.ar.server.db.service.ComboService;
import com.gxar.quick.ar.server.db.service.OrderService;
import com.gxar.quick.ar.server.db.service.TransactionService;
import com.gxar.quick.ar.server.db.service.UserService;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author nice
 * @version 1.0
 * @created 2023/11/15.
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class WechatPaySDK {

    private final JsapiService jsapiService;

    private final TransactionService transactionService;

    private final OrderService orderService;

    private final UserService userService;

    private final UserConfigMapper userConfigMapper;

    private final SlotMapper slotMapper;

    private final WorksMapper worksMapper;

    private final ComboService comboService;

    private final WechatPayProperties wechatPayProperties;

    private static final String SIGN_BODY_PREFIX = "prepay_id=";
    public static final String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";

    public WechatPrepayResponse prepay(String appId, WechatPrepayRequest param) {
        WechatPrepayResponse result = new WechatPrepayResponse();
        PrepayRequest request = getPrepayRequest(appId, param);
        // 调用下单方法，得到应答
        PrepayResponse response = jsapiService.prepay(request);
        result.setPrepayId(response.getPrepayId());
        long timestamp = System.currentTimeMillis() / 1000;
        result.setTimestamp(timestamp);
        UUID uuid = UUID.randomUUID();
        String nonceStr = uuid.toString().replace("-", "");
        result.setNonceStr(nonceStr);
        String paySign = AesUtils.getSignWithConfig(appId, timestamp, nonceStr,
                SIGN_BODY_PREFIX + response.getPrepayId());
        result.setPaySign(paySign);
        return result;
    }

    @NotNull
    private PrepayRequest getPrepayRequest(String appId, WechatPrepayRequest param) {
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        //单位：分
        amount.setTotal(param.getAmount());
        request.setAmount(amount);
        request.setAppid(appId);
        request.setMchid(WechatPayConstant.MERCHANT_ID);
        request.setDescription(param.getDescription());
        request.setNotifyUrl(wechatPayProperties.getNotifyUrl());
        request.setOutTradeNo(param.getOutTradeNo());
        request.setAttach(param.getAttach());
        Payer payer = new Payer();
        payer.setOpenid(param.getOpenId());
        request.setPayer(payer);
        request.setTimeExpire(DateUtil.format(param.getTimeExpire(), RFC3339_FORMAT));
        return request;
    }

    public WechatTransactionResponse queryTransaction(String orderId) {
        AssertUtils.notNull(orderId, SystemCodeEnum.PARAM_ERROR.getRet(), "订单id不能为空");
        //先从db取支付信息

        //如果没有再调微信接口
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(WechatPayConstant.MERCHANT_ID);
        request.setOutTradeNo(orderId);
        Transaction transaction = jsapiService.queryOrderByOutTradeNo(request);
        log.info("transaction:{}", transaction);
        WechatTransactionResponse result = JacksonUtils.parseObject(transaction.toString(),
                WechatTransactionResponse.class);
        return result;
    }
}
